package chen.huai.jie.spring.xmlconfig.mybatis;

import org.apache.ibatis.type.EnumOrdinalTypeHandler;
import org.apache.ibatis.type.EnumTypeHandler;
import org.apache.ibatis.type.TypeHandler;

import javax.persistence.*;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class EntityPortray {
    private String name;
    private Map<String, String> columnMap = new HashMap();
    private Map<String, Class<?>> columnTypeMap = new HashMap();
    private Map<String, Class<? extends TypeHandler>> columnTypeHandlers = new HashMap();
    private Class<?> entityClass;
    private String primaryProperty;
    private String primaryColumn;
    private Class<?> primaryType;
    private GeneratedValue generatedValue;

    public EntityPortray(Class<?> entity) {
        if (entity.getAnnotation(Table.class) != null) {
            this.entityClass = entity;
        } else {
            this.entityClass = this.getEntityType(entity);
        }

        this.parse();
    }

    private List<Field> findFields(Class<?> clazz) {
        List<Field> fields = (List) Stream.of(clazz.getDeclaredFields()).collect(Collectors.toList());
        Class<?> superClass = clazz.getSuperclass();
        if (superClass != null) {
            fields.addAll(this.findFields(superClass));
        }

        return fields;
    }

    private void parse() {
        Table table = (Table) this.entityClass.getAnnotation(Table.class);
        if (table != null) {
            this.name = table.name();
        } else {
            this.name = this.entityClass.getSimpleName().toLowerCase();
        }

        List<Field> fields = this.findFields(this.entityClass);
        Iterator var3 = fields.iterator();

        while (var3.hasNext()) {
            Field field = (Field) var3.next();
            if (!Modifier.isStatic(field.getModifiers()) && !Modifier.isFinal(field.getModifiers()) && field.getAnnotation(Transient.class) == null) {
                Column column = (Column) field.getDeclaredAnnotation(Column.class);
                if (field.getAnnotation(Id.class) != null) {
                    this.primaryColumn = column.name();
                    this.primaryProperty = field.getName();
                    this.primaryType = field.getType();
                    this.generatedValue = (GeneratedValue) field.getAnnotation(GeneratedValue.class);
                }

                String columnName = field.getName();
                if (column != null) {
                    columnName = column.name();
                }

                this.columnMap.put(field.getName(), columnName);
                this.columnTypeMap.put(field.getName(), field.getType());
                Enumerated enumerated = (Enumerated) field.getAnnotation(Enumerated.class);
                if (enumerated != null) {
                    if (enumerated.value() == EnumType.STRING) {
                        this.columnTypeHandlers.put(field.getName(), EnumTypeHandler.class);
                    } else {
                        this.columnTypeHandlers.put(field.getName(), EnumOrdinalTypeHandler.class);
                    }
                }
            }
        }

    }

    private Class<?> getEntityType(Class<?> mapper) {
        Type[] types = mapper.getGenericInterfaces();
        Type[] var3 = types;
        int var4 = types.length;

        for (int var5 = 0; var5 < var4; ++var5) {
            Type type = var3[var5];
            if (type instanceof ParameterizedType) {
                ParameterizedType parameterizedType = (ParameterizedType) type;
                Class rawType = (Class) parameterizedType.getRawType();
                if (AutoMapper.class.isAssignableFrom(rawType)) {
                    Class entityType = (Class) parameterizedType.getActualTypeArguments()[0];
                    if (entityType.isAnnotationPresent(Table.class)) {
                        return entityType;
                    }
                }
            }
        }

        return null;
    }

    public String getPrimaryProperty() {
        return this.primaryProperty;
    }

    public void setPrimaryProperty(String primaryProperty) {
        this.primaryProperty = primaryProperty;
    }

    public String getPrimaryColumn() {
        return this.primaryColumn;
    }

    public void setPrimaryColumn(String primaryColumn) {
        this.primaryColumn = primaryColumn;
    }

    public Class<?> getPrimaryType() {
        return this.primaryType;
    }

    public void setPrimaryType(Class<?> primaryType) {
        this.primaryType = primaryType;
    }

    public String getName() {
        return this.name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Map<String, String> getColumnMap() {
        return this.columnMap;
    }

    public String getClumn(String property) {
        return (String) this.columnMap.get(property);
    }

    public void setColumnMap(Map<String, String> columnMap) {
        this.columnMap = columnMap;
    }

    public Map<String, Class<?>> getColumnTypeMap() {
        return this.columnTypeMap;
    }

    public Class<?> columnType(String property) {
        return (Class) this.columnTypeMap.get(property);
    }

    public void setColumnTypeMap(Map<String, Class<?>> columnTypeMap) {
        this.columnTypeMap = columnTypeMap;
    }

    public Class<?> getEntityClass() {
        return this.entityClass;
    }

    public void setEntityClass(Class<?> entityClass) {
        this.entityClass = entityClass;
    }

    public GeneratedValue getGeneratedValue() {
        return this.generatedValue;
    }

    public void setGeneratedValue(GeneratedValue generatedValue) {
        this.generatedValue = generatedValue;
    }

    public Map<String, Class<? extends TypeHandler>> getColumnTypeHandlers() {
        return this.columnTypeHandlers;
    }

    public void setColumnTypeHandlers(Map<String, Class<? extends TypeHandler>> columnTypeHandlers) {
        this.columnTypeHandlers = columnTypeHandlers;
    }

}
